package org.yunai.swjg.server.core.service;

import org.slf4j.Logger;
import org.yunai.swjg.server.core.message.GameMessage;
import org.yunai.swjg.server.core.session.GameSession;
import org.yunai.swjg.server.rpc.message.C_S.C_S_LoginReq;
import org.yunai.swjg.server.rpc.message.C_S.C_S_SceneEnterReq;
import org.yunai.yfserver.common.LoggerFactory;
import org.yunai.yfserver.message.IMessage;
import org.yunai.yfserver.server.IMessageProcessor;
import org.yunai.yfserver.server.QueueMessageProcessor;

/**
 * 游戏消息处理器
 * User: yunai
 * Date: 13-4-24
 * Time: 下午3:51
 */
public class GameMessageProcessor implements IMessageProcessor {

    private static final Logger LOGGER = LoggerFactory.getLogger(LoggerFactory.Logger.msg, GameMessageProcessor.class);

    /**
     * 主消息队列<br />
     * 处理以下几种消息:
     * <pre>
     *     1. 系统内部消息
     *     2. 玩家在非场景下的消息
     * </pre>
     */
    private QueueMessageProcessor mainMessageProcessor;

    public GameMessageProcessor(QueueMessageProcessor mainMessageProcessor) {
        this.mainMessageProcessor = mainMessageProcessor;
    }

    @Override
    public void start() {
        mainMessageProcessor.start();
    }

    @Override
    public void stop() {
        mainMessageProcessor.stop();
    }

    @Override
    public void put(IMessage message) {
        if (message instanceof C_S_LoginReq) {
            GameSession gSession = ((GameMessage) message).getSession();
            if (gSession == null) {
                LOGGER.error("[put] [message({}) has no session].", message.getCode());
                return;
            }
            Online online = gSession.getOnline();
            if (online == null) {
                mainMessageProcessor.put(message);
            } else {
                if (!online.validateMessage(message)) {
                    LOGGER.error("[put] [online.state({}) can't put message({})].", online.getState(), message.getCode());
                    return;
                }
                mainMessageProcessor.put(message);
            }
        } else if (message instanceof GameMessage) {
            GameSession gSession = ((GameMessage) message).getSession();
            if (gSession == null) {
                LOGGER.error("[put] [message({}) has no session].", message.getCode());
                return;
            }
            Online online = gSession.getOnline();
            if (online == null) {
                LOGGER.error("[put] [message({}) has no online].", message.getCode());
                return;
            }
            if (!online.validateMessage(message)) {
                LOGGER.error("[put] [online.state({}) can't put message({})].", online.getState(), message.getCode());
                return;
            }
            if (online.isInScene() && !isPutToMainMessageProcessor(message)) {
                online.putMessage(message);
            } else {
                mainMessageProcessor.put(message);
            }
        } else {
            mainMessageProcessor.put(message);
        }

        // TODO PlayerQueueMessage
        // TODO ProcessEventMessage
    }

    /**
     * 判断消息是否需要强制放入主消息队列
     *
     * @param msg 消息
     * @return true、false
     */
    private boolean isPutToMainMessageProcessor(IMessage msg) {
        switch (msg.getCode()) {
            case C_S_SceneEnterReq.CODE:
//            case C_S_SceneSwitchReq.CODE: // TODO 放到场景线程
//            case C_S_RepEnterReq.CODE: // TODO 放到场景线程
//            case C_S_RepLeaveReq.CODE: // TODO 放到场景线程
                return true;
            default:
                return false;
        }
    }

    @Override
    public boolean isFull() {
        return mainMessageProcessor.isFull();
    }

    /**
     * @return 主消息处理器的线程编号. 可能返回空
     */
    public Long getThreadId() {
        return mainMessageProcessor.getThreadId();
    }
}
